//
// Created by v on 24-11-26.
//

#include "CMUIShowWithLVGL.h"

#include <stdlib.h>
#include <unistd.h>

#include "jpeglib.h"
#include "turbojpeg.h"

#include "rt_print.h"
#include "libyuv.h"

CMUIShowWithLVGL::CMUIShowWithLVGL() {
    rtdebug("lgvl version [%d.%d.%d]", LVGL_VERSION_MAJOR, LVGL_VERSION_MINOR, LVGL_VERSION_PATCH);
    timeShowLast = 0;
    labelImage = NULL;
    labelMain = NULL;
    labelText = NULL;
    image_buffer = NULL;
    image_buffer_size = 0;
}

CMUIShowWithLVGL::~CMUIShowWithLVGL() noexcept
{
    ui_deinit();
    if (image_buffer)
    {
        free(image_buffer);
    }
}

int CMUIShowWithLVGL::labelTextInit() {
    labelText = lv_label_create(lv_screen_active());
    lv_label_set_text(labelText, "I'm recognizing your face");
    lv_obj_set_style_text_color(lv_screen_active(), lv_color_hex(0xffffff), LV_PART_MAIN);
    lv_obj_set_style_text_font(labelText, &lv_font_montserrat_36, LV_PART_MAIN);
    lv_obj_align(labelText, LV_ALIGN_TOP_MID, -260, 0);
    return 0;
}

int CMUIShowWithLVGL::showMain() {
    ui_init();
    lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(0x003a57), LV_PART_MAIN);

    /*Create a white label, set its text and align it to the center*/
    labelMain = lv_label_create(lv_screen_active());
    lv_label_set_text(labelMain, "Hello lvgl");
    lv_obj_set_style_text_color(lv_screen_active(), lv_color_hex(0xffffff), LV_PART_MAIN);
    lv_obj_set_style_text_font(labelMain, &lv_font_montserrat_48, LV_PART_MAIN);
    lv_obj_align(labelMain, LV_ALIGN_BOTTOM_MID, -280, 0);
    lv_timer_enable(true);

    labelTextInit();

    labelImage = lv_canvas_create(lv_screen_active());
//    labelImage = lv_image_create(lv_screen_active());
    lv_obj_set_size(labelImage, 960, 1280);
    lv_obj_align(labelImage, LV_ALIGN_TOP_RIGHT, 0, 0);

    return 0;
}

int CMUIShowWithLVGL::uiShowImage(const char *image_file)
{
    if (!labelImage)
    {
        return -1;
    }
    char *img_data = NULL;
    int img_len = 0;
    cm_read_file_data(image_file, &img_data, &img_len);
    rtdebug("image size [%d]", img_len);

    return uiShowImage(img_data, img_len);
}

int CMUIShowWithLVGL::uiShowImage(const char            *image_buf,
                                  unsigned long long int image_buf_size)
{
    tjhandle handle = tjInitDecompress();
    if (!handle)
    {
        rterror("error create decompress");
        return -2;
    }
    int width, height, subsample, colorspace;
    tjDecompressHeader3(handle, (const unsigned char*)image_buf, image_buf_size, &width, &height, &subsample, &colorspace);
//    rtdebug("width height [%d x %d] subsample [%d] colorspace [%d]", width, height, subsample, colorspace);

    int flags = 0;
    int pitch = width * tjPixelSize[TJPF_BGR];
    unsigned long long image_length = height * pitch;
    if (!image_buffer)
    {
        image_buffer = (unsigned char*)malloc(image_length);
        image_buffer_size = image_length;
    }
    if (image_length > image_buffer_size)
    {
        image_buffer = realloc(image_buffer, image_length);
        image_buffer_size = image_length;
    }

    tjDecompress2(handle, (const unsigned char*)image_buf, image_buf_size, (unsigned char*)image_buffer, width, pitch, height, TJPF_BGR, flags);

#if 0
    lv_img_dsc_t imgDsc;
    memset(&imgDsc, 0, sizeof(imgDsc));
    imgDsc.header.flags = 0;
    imgDsc.header.magic = LV_IMAGE_HEADER_MAGIC;
    imgDsc.header.cf = LV_COLOR_FORMAT_RGB888;
    imgDsc.header.w = width;
    imgDsc.header.h = height;
    imgDsc.data_size = image_length;
    imgDsc.data = (const uint8_t*)image_buffer;
    lv_img_set_src(labelImage, &imgDsc);
#endif

    lv_canvas_set_buffer(labelImage, image_buffer, width, height,
                                 LV_COLOR_FORMAT_RGB888);

    tjDestroy(handle);
    return 0;
}

int CMUIShowWithLVGL::uiShowImage(const char *buf, unsigned long long buf_size, int width, int height)
{
    if (!labelImage)
    {
        return -1;
    }
    if (!image_buffer)
    {
        image_buffer = malloc(buf_size);
        image_buffer_size = buf_size;
    }
    if (buf_size > image_buffer_size)
    {
        image_buffer = realloc(image_buffer, buf_size);
        image_buffer_size = buf_size;
    }
    memcpy(image_buffer, buf, buf_size);
    lv_canvas_set_buffer(labelImage, (void*)buf, width, height, LV_COLOR_FORMAT_RGB888);
    return 0;
}

static const char *getenv_default(const char *name, const char *dflt)
{
    return getenv(name) ? : dflt;
}

int CMUIShowWithLVGL::runOnce()
{
    uint32_t idle_time;
    unsigned long long now = cm_gettime_milli();
    if (now - timeShowLast >= 1000 && labelMain)
    {
        char timestr[32] = {0};
        time_t t = time(NULL);
        struct tm *tm = localtime(&t);
        strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm);
        lv_label_set_text(labelMain, timestr);
        timeShowLast = now;
    }

            lv_task_handler();
    idle_time = lv_timer_handler(); /*Returns the time to the next timer execution*/
    usleep(10000);
    return 0;
}

int  CMUIShowWithLVGL::runLoop()
{
    /*Handle LVGL tasks*/
    while(1) {
        runOnce();
    }
    return 0;
}

int CMUIShowWithLVGL::ui_init()
{
    lv_init();
    const char *device = getenv_default("LV_LINUX_FBDEV_DEVICE", "/dev/fb0");
    lv_display_t * disp = lv_linux_fbdev_create();

#if LV_USE_EVDEV
    lv_linux_init_input_pointer(disp);
#endif

    lv_linux_fbdev_set_file(disp, device);
    return 0;
}

int CMUIShowWithLVGL::ui_deinit()
{
    lv_deinit();
    return 0;
}
int CMUIShowWithLVGL::init() { return 0; }
int CMUIShowWithLVGL::deinit() { return 0; }
int CMUIShowWithLVGL::ctl(int type, void *args) { return 0; }
int CMUIShowWithLVGL::run() {

    return 0;
}
int CMUIShowWithLVGL::uiShowText(const char *text) {
    if (!labelText)
        return -1;

    lv_label_set_text(labelText, text);
    return 0;
}
